import React, { PureComponent } from 'react';
import propTypes from 'prop-types';

/**
 * @description Canvas滑动刻度尺组件
 * @author 简佳成
 * @date 2019-12-20
 * @extends {PureComponent}
 * @class RotaryScale
 * @height 刻度尺高度 Number
 * @maxScale 最大刻度 Number
 * @startValue 开始的值 Number
 * @region 区间 Array
 * @background 刻度尺背景颜色 String
 * @color 刻度线和字体的颜色 String
 */
class RotaryScale extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {};
    (this.height = props.height || 80),
      (this.width = props.width || document.documentElement.clientWidth),
      (this.maxScale = props.maxScale || 100),
      (this.minScale = props.minScale || 0),
      (this.startValue = props.startValue || 0),
      (this.region = props.region || false),
      (this.background = props.background || false),
      (this.color = props.color || false),
      (this.onChange = props.onChange);
  }

  static propTypes = {
    height: propTypes.number.isRequired,
    width: propTypes.number.isRequired,
    onChange: propTypes.func.isRequired,
  };

  componentDidMount() {
    this.init();
  }

  /**
   * @description 初始化刻度尺
   * @memberof RotaryScale
   * 1.完成刻度尺容器的宽高设置
   * 2.生成canvas
   * 3.生成刻度尺
   * 4.注册事件监听函数
   */
  init = () => {
    var rulerWrap = this.scale; //获取容器
    rulerWrap.style.height = this.height < 50 ? 50 + 'px' : this.height + 'px';
    rulerWrap.style.width = this.width;

    //最大刻度的小值是50
    this.maxScale = this.maxScale < 50 ? 50 : this.maxScale;

    if (this.startValue > this.maxScale) {
      this.startValue = this.maxScale;
    }

    var minSildeNum = this.minScale; //最小滑动的值
    var maxSildeNum = this.maxScale; //最大滑动的值

    if (this.region) {
      minSildeNum = Math.floor(this.region[0]);
      maxSildeNum = Math.floor(this.region[1]);
    }

    var count = this.startValue; //初始值

    var winWidth = rulerWrap.offsetWidth; //容器宽度
    var division = winWidth / 50; //每个刻度的距离 分割线
    //刻度值数组
    var scaleValueList = [];
    for (var i = this.minScale; i <= this.maxScale; i += 10) {
      scaleValueList.push(i);
    }

    var canvas = rulerWrap.getElementsByTagName('canvas')[0]; //获取容器下的canvas标签

    //没有canvas就创建一个
    if (!canvas) {
      canvas = document.createElement('canvas'); //创建canvas标签
      canvas.width = winWidth;
      canvas.height = this.height;
      rulerWrap.appendChild(canvas);
    }

    // 设置canvas宽高
    var ctx = canvas.getContext('2d');
    canvas.width = winWidth;
    canvas.height = this.height;

    /*if (window.devicePixelRatio) {
            canvas.width = window.devicePixelRatio * winWidth;
            canvas.height = window.devicePixelRatio * this.height;
            ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
        } */

    //初次生成刻度尺，滑动后重绘刻度尺    
    this.drawRuler(count, ctx, division, scaleValueList);

    //滑动相关
    var initX = 0, //初始x 距离 TODO:全局变量
      endX = 0, //结束x 距离
      distanceX = 0, //移动距离
      _distanceX = 0, // 判断用的移动距离
      lastX = count; //上次移动距离

    if (!canvas) return false;

    //手指按下
    canvas.addEventListener(
      'touchstart',
      e => {
        initX = e.targetTouches[0].pageX;
      },
      false
    );

    //手指滑动
    canvas.addEventListener(
      'touchmove',
      e => {
        endX = e.targetTouches[0].pageX;
        moveEvent();
      },
      false
    );

    //手指抬起
    canvas.addEventListener(
      'touchend',
      e => {
        lastX = count;
        overEvent();
      },
      false
    );

    var isMouseDown = false; //鼠标是否按下

    //鼠标按下
    canvas.addEventListener(
      'mousedown',
      e => {
        isMouseDown = true;
        initX = e.layerX;
      },
      false
    );

    //鼠标移动
    canvas.addEventListener(
      'mousemove',
      e => {
        if (!isMouseDown) {
          return false;
        }
        endX = e.layerX;
        moveEvent();
      },
      false
    );

    //鼠标抬起&离开
    canvas.addEventListener(
      'mouseup',
      e => {
        lastX = count;
        isMouseDown = false;
        overEvent();
      },
      false
    );

    canvas.addEventListener(
      'mouseleave',
      e => {
        if (isMouseDown) {
          lastX = count;
          isMouseDown = false;
          overEvent();
        }
      },
      false
    );

    //手指&鼠标移动事件触发执行的函数
    const moveEvent = () => {
      distanceX = Math.floor((endX - initX) / (winWidth / 50));
      if (distanceX === _distanceX) {
        return false;
      }
      _distanceX = distanceX;
      count = lastX + distanceX;

      if (count >= this.maxScale || count <= this.minScale) {
        count = count >= this.maxScale ? this.maxScale : this.minScale;
      }
      this.drawRuler(count, ctx, division, scaleValueList);

      if (this.isConstant) {
        params.success && params.success(count);
      }
      this.onChange && this.onChange(count);
    };

    //手指&鼠标结束事件触发执行的函数
    const overEvent = () => {
      if (count > maxSildeNum) {
        lastX = count = count > maxSildeNum ? maxSildeNum : count;
      } else if (count < minSildeNum) {
        lastX = count = count < minSildeNum ? minSildeNum : count;
      } else {
      }
      this.drawRuler(count, ctx, division, scaleValueList);

      //返回最后的值
      this.onChange && this.onChange(count);
    };
  };

  /**
   * @description 每次滑动重绘刻度线
   * @param {*} count 滑动到的位置
   * @param {*} ctx canvas绘制上下文
   * @param {*} division 每个刻度的长度 如果均分50份 division = winWidth / 50;
   * @param {*} scaleValueList 无效参数 暂时弃用
   */
  drawRuler = (count, ctx, division, scaleValueList) => {
    // 开始位置-25格 居中显示
    let now = count;
    count = count - 25;

    //清空画布
    ctx.clearRect(0, 0, winWidth, this.height);

    //刻度尺背景
    if (this.background) {
      ctx.fillStyle = this.background;
      ctx.fillRect(0, 0, this.width, this.height);
    }

    //画刻度线
    for (var i = this.minScale; i <= this.maxScale; i++) {
      ctx.beginPath();
      ctx.save();
      ctx.strokeStyle = 'rgba(255,255,255,0.4)';
      ctx.lineWidth = 1;
      ctx.lineCap = 'round';

      if (i % 5 === 0) {
        // 每五格一个长竖线
        ctx.moveTo(division * i - count * division, Math.floor(this.height * 0.55));
        ctx.lineTo(division * i - count * division, Math.floor(this.height * 0.35));
      } else {
        // 否则就是短竖线
        ctx.moveTo(division * i - count * division, Math.floor(this.height * 0.55));
        ctx.lineTo(division * i - count * division, Math.floor(this.height * 0.45));
      }
      if (i % 10 === 0 && i != now) {
        // 每十格一个长竖线+文字指示
        ctx.moveTo(division * i - count * division, Math.floor(this.height * 0.55));
        ctx.lineTo(division * i - count * division, Math.floor(this.height * 0.35));
        ctx.font = '14px Arial';
        ctx.fillStyle = this.color ? this.color : 'white';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(
          i.toString() + '°',
          division * i - count * division,
          Math.floor(this.height * 0.25)
        );
      }
      ctx.stroke();
      ctx.restore();
      ctx.closePath();
    }

    this.centerLine(ctx, now, winWidth);
    //中心刻度线
  };

  /**
   * @description 绘制刻度尺中间的指示图像集合
   * @param {*} ctx canvas的Context
   * @param {*} now 现在的数值
   * @param {*} winWidth 屏幕宽度
   */
  centerLine = (ctx, now, winWidth) => {
    // 绘制中心竖线
    ctx.beginPath();
    ctx.save();
    ctx.strokeStyle = 'white';
    ctx.lineWidth = 2;
    ctx.lineCap = 'round';
    ctx.moveTo(winWidth / 2, Math.floor(this.height * 0.55));
    ctx.lineTo(winWidth / 2, Math.floor(this.height * 0.2));
    ctx.stroke();

    //绘制刻度文字
    ctx.font = '14px Arial';
    ctx.fillStyle = this.color ? this.color : 'white';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(now + '°', winWidth / 2, Math.floor(this.height * 0.08));

    // 绘制三角形指示图像
    ctx.moveTo(winWidth / 2, this.height * 0.62); 
    ctx.lineTo(winWidth / 2 - 3, this.height * 0.7); 
    ctx.lineTo(winWidth / 2 + 3, this.height * 0.7); 
    ctx.fillStyle = 'white'; 
    ctx.fill();

    // 绘制未闭合圆环
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = 'white';
    ctx.arc(
      winWidth / 2,
      this.height * 0.88,
      this.height * 0.08,
      (20 / 180) * Math.PI,
      (2 - 20 / 180) * Math.PI
    );
    ctx.stroke();

    // 绘制中心圆环
    ctx.beginPath();
    ctx.arc(winWidth / 2, this.height * 0.88, this.height * 0.025, 0, 2 * Math.PI);
    ctx.fillStyle = 'white';
    ctx.fill();

    ctx.closePath();
  };

  render() {
    const { height, width } = this.props;
    return <div style={{ width: width, height: height }} ref={scale => (this.scale = scale)}></div>;
  }
}
export default RotaryScale;
